/*
 * Copyright (C) 2011 Michael Widmer <widmm8@bfh.ch>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ch.bfh.aeneas.navigation.route;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import ch.bfh.aeneas.R;
import ch.bfh.aeneas.exchange.intent.AeneasIntent;
import ch.bfh.aeneas.exchange.data.Node;
import ch.bfh.aeneas.exchange.data.Route;
import ch.bfh.aeneas.navigation.app.NavigationActivity;
import ch.bfh.aeneas.exchange.Scope;

/**
 * This is a helper class that gets called by RouteMe, when no route or place
 * for navigation has been specified. The user can choose a route or a node from
 * lists in this activity and use them for travelling afterwards in RouteMe.
 * @author Michael Widmer <widmm8@bfh.ch>
 */
public class RoutePickMe extends NavigationActivity {

    protected BroadcastReceiver mAnswerListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            try {
                Log.i(LOG_TAG, "Received answer... trying to handle!");
                handleAnswer(arg1);
            } catch(Exception ex) {
                Log.w(LOG_TAG, "any unknown error happened: "+ex.getMessage()+" -> "+ex.getStackTrace());
            }
        }
    };
    
    private static final String LOG_TAG = "RoutePickMe";
    
    protected int mRequestId;
    protected int mStep;
    protected String mCategory;
    protected String mType;
    protected String mPara;
    private Location mCurrentLocation;
    
    protected static final int PICK_CHOICE = 1;
    protected static final int PICK_ROUTE = 2;
    protected static final int PICK_NODE = 3;
    protected static final int PICK_RANGE = 4;
    
    protected static final int STEP_PREPARE = -1;
    protected static final int STEP_WAITING = 0;
    protected static final int STEP_CATEGORY = 1;
    protected static final int STEP_RANGE = 2;
    protected static final int STEP_ITEM = 3;
    
    @Override
    /**
     * {@inheritDoc}
     */
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle, R.layout.routeme);    
        
        mStep = STEP_PREPARE;
    }
    
    @Override
    /**
     * {@inheritDoc}
     */
    public void onResume() {
        super.onResume();
        
        Log.i(LOG_TAG, "In onResume!");
        
        if(mStep == STEP_PREPARE) {
            Log.i(LOG_TAG, "First step - showing selection!");
            speech(getString(R.string.state_wait_for_position));
            //mStep = STEP_CATEGORY;
        } else {
            Log.i(LOG_TAG, "Not first step - startup!");
            startUp();
        }
    }

    @Override
    /**
     * {@inheritDoc}
     */
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(LOG_TAG, "Received resultCode: "+resultCode+" and requestCode: "+requestCode);
        
        switch(requestCode) {
            case PICK_CHOICE:
                if(resultCode == Activity.RESULT_OK) {
                    int selected = data.getIntExtra("selectedIndex", -1);
                    
                    mType = selected == 0?"route":"place";
                    mPara = selected == 0?"to":"around";
                    mCategory = selected == 0?AeneasIntent.CATEGORY_ROUTE:AeneasIntent.CATEGORY_NODE;
                    
                    mStep = STEP_RANGE;
                    
                    Log.i(LOG_TAG, "Picked - waiting for onResume");
                    
                } else {
                    setResult(Activity.RESULT_CANCELED);
                    finish();
                }
                break;
            case PICK_RANGE:
                if(resultCode == Activity.RESULT_OK) {
                    
                    Log.i(LOG_TAG, "Entered range - going to request items");
                    int range = data.getIntExtra("input", 100);
                    requestItems(range);
                    
                } else {
                    mStep = STEP_CATEGORY;
                }
                break;
            case PICK_ROUTE:
                if(resultCode == Activity.RESULT_OK) {
                    Route pickedRoute = (Route) data.getParcelableExtra("selectedValue");
                    Log.i(LOG_TAG, "Picked route: "+pickedRoute.getName());

                    Intent routeIntent = new Intent();
                    routeIntent.putExtra("route", pickedRoute);
                    
                    this.setResult(Activity.RESULT_OK, routeIntent);
                    finish();
                } else {
                    mStep = STEP_CATEGORY;
                }
                break;
            case PICK_NODE:
                if(resultCode == Activity.RESULT_OK) {
                    Node pickedNode = (Node) data.getParcelableExtra("selectedValue");
                    Log.i(LOG_TAG, "Picked node: "+pickedNode.getName());

                    Intent nodeIntent = new Intent();
                    nodeIntent.putExtra("to", (Parcelable) pickedNode);

                    this.setResult(Activity.RESULT_OK, nodeIntent);
                    finish();
                } else {
                    mStep = STEP_CATEGORY;
                }
                break;
            default:
                setResult(Activity.RESULT_CANCELED);
                finish();
        }
    }
    
    @Override
    /**
     * {@inheritDoc}
     */
    protected void onPositionConnected() {
        if(mStep == STEP_PREPARE) {
            startListening();
        }
    }

    @Override
    /**
     * {@inheritDoc}
     */
    protected void onPositionReceivedFirst(Location l) {
        stopListening();
        mCurrentLocation = l;
        mStep = STEP_CATEGORY;
        startUp();
    }
    
    private void startUp() {
        
        Log.i(LOG_TAG, "In startup - at step: "+mStep);
        
        switch(mStep) {
            case STEP_CATEGORY:
                Log.i(LOG_TAG, "Asking for category!");
                showPickCategory();
                break;
            case STEP_RANGE:
                Log.i(LOG_TAG, "Asking for range!");
                showRangeInput();
                break;
            case STEP_ITEM:
                Log.i(LOG_TAG, "Asking for item!");
                break;
            case STEP_WAITING:
                Log.i(LOG_TAG, "Waiting...");
            default:
                break;
        }
    }
    
    private void showPickCategory() {
        Log.i(LOG_TAG, "Showing category-selection");
        String[] options = { getString(R.string.route_item_routes), getString(R.string.route_item_nodes)};
        
        Intent i = new Intent(AeneasIntent.ACTION_SELECT);
        i.addCategory(AeneasIntent.CATEGORY_STRING);
        i.putExtra("values", options);
        i.putExtra("title", "Kategorien");
        
        startActivityForResult(i, PICK_CHOICE);
    }
    
    private void showRangeInput() {
        SharedPreferences p = super.getApplicationPreferences();
        String range = p.getString("around_range", "-1");
        
        Intent i = new Intent(AeneasIntent.ACTION_INPUT);
        i.addCategory(AeneasIntent.CATEGORY_DATA);
        i.putExtra("default",range);
        i.putExtra("numeric", true);
        i.putExtra("title", getString(R.string.around_enter_radius));
        
        startActivityForResult(i, PICK_RANGE);
    }
    
    //protected void requestItems(Intent data) {
    private void requestItems(int range) {
        AeneasIntent i = new AeneasIntent(AeneasIntent.ACTION_REQUEST);
        i.addCategory(mCategory);
        i.putExtra("scope", Scope.LOCAL);
        i.putExtra("type", mType);
        i.putExtra("around", mCurrentLocation);
        if(range > -1) {
            i.putExtra("range", range);
        }

        IntentFilter infi = new IntentFilter(AeneasIntent.ACTION_RESPONSE);
        getApplicationContext().registerReceiver(mAnswerListener, infi);

        mRequestId = i.getRequestId();

        mStep = STEP_WAITING;
        super.sendBroadcast(i);
    }

    private void removeAnswerListener() {
        super.getApplicationContext().unregisterReceiver(mAnswerListener);
    }

    private void handleAnswer(Intent intent) {
        int requestId = -1;
        Log.i(LOG_TAG, "Checking for extra 'requestId'");
        if(intent.hasExtra("requestId")) {
            Log.i(LOG_TAG, "intent seems to be having 'requestId'");
            requestId = intent.getIntExtra("requestId", -1);
        }
        Log.i(LOG_TAG, "Just after checking for extra 'requestId'");
        if(requestId == mRequestId) {
            removeAnswerListener();
            
            Log.i(LOG_TAG, "Checking for extra 'routes'");
            
            if(intent.hasExtra("route0")) {
                Intent request = new Intent(AeneasIntent.ACTION_SELECT);
                request.addCategory(AeneasIntent.CATEGORY_ROUTE);                
                request.putExtras(intent);
                request.putExtra("title", getString(R.string.route_item_routes));
                mStep = STEP_ITEM;
                startActivityForResult(request, PICK_ROUTE);
            } else if(intent.hasExtra("address0")) {
                Intent request = new Intent(AeneasIntent.ACTION_SELECT);
                request.addCategory(AeneasIntent.CATEGORY_NODE);
                request.putExtras(intent);
                request.putExtra("title", getString(R.string.route_item_nodes));                
                mStep = STEP_ITEM;
                startActivityForResult(request, PICK_NODE);
            }
        } else {
            Log.i(LOG_TAG, "Received answer with wrong requestId: "+requestId+", but expected: "+mRequestId);
        }
    }
}
